- Introducción
- Motivación
- Empezando a caminar con Shiny
- Componentes básicas de una aplicación Shiny
- User interface (ui)
- Layouts
- Widgets: Inputs
- Server
- Widgets: Outputs
- Resctividad
07 de Junio, 2017
Hasta el momento hemos hablado de la creación de documentos mediante R Markdown, interactivos o no, pensando en un uso local.
Estamos en la sociedad de la información e internet lo domina todo. ¿Podemos utilizar internet para ayudar en la investigación reproducible?
Shiny es una herramienta perfecta para compartir nuestros estudios, permitiendo el acceso a la información. Esto genera numerosos beneficios:
Paso 1. Abrimos RStudio.
Paso 2. Instalamos el paquete "shiny" desde CRAN (en caso de no haberlo instalado previamente):
install.packages("shiny", dependencies = TRUE)
Paso 3. Seleccionamos File >> New File >> Shiny Web App….
Paso 4. Indicamos el nombre de la aplicación, el número de archivos que queremos y el directorio de creación.
Si no cerramos la app, esta se queda ejecutándose en R y no podremos seguir trabajando.
Para crear una aplicación Shiny es suficiente con tener los scripts ui.R y server.R (app.R) dentro de la misma carpeta. El nombre de estos scripts no se puede cambiar.
La estructura es la siguiente:
1. Estructura general (layouts de página)
2. División de la página (layouts)
3. Contenido de la página (widgets)
ui <- fluidPage(
# Título de la aplicación
titlePanel("Shiny - fluidPage")
)
ui <- bootstrapPage(
# Título de la aplicación
titlePanel("Shiny - bootstrapPage")
)
# Definición del server
server <- function(input, output) {}
# App completa con los componentes ui y server
shinyApp(ui, server)
Los elementos de la página se definen de arriba abajo.
La separación entre los elementos es con comas.
Gran flexibilidad en la configuración del IU.
Los layouts se pueden combinar unos dentro de otros, anidados.
ui <- fluidPage(
titlePanel("Shiny - sidebarLayout"),
sidebarLayout(
# Barra lateral con un selector deslizante
sidebarPanel(
sliderInput("obs",
"Número de observaciones:",
min = 0, max = 1000,
value = 500)
),
mainPanel(
plotOutput("distPlot")
)
)
)
server <- function(input, output) {
output$distPlot <- renderPlot({
hist(rnorm(input$obs))
})
}
shinyApp(ui, server)
ui <- fluidPage(
titlePanel("Shiny - verticalLayout"),
verticalLayout(
a(href="http://example.com/link1", "Link Primero"),
a(href="http://example.com/link2", "Link Segundo"),
a(href="http://example.com/link3", "Link Tercero")
)
)
server <- function(input, output) {}
shinyApp(ui, server)
ui <- fluidPage(
titlePanel("Shiny - splitLayout"),
splitLayout(
plotOutput("plot1"),
plotOutput("plot2")
)
)
server <- function(input, output) {
output$plot1 <- renderPlot(plot(cars))
output$plot2 <- renderPlot(plot(pressure))
}
shinyApp(ui, server)
ui <- fluidPage(
titlePanel("Shiny - conditionalPanel"),
sidebarPanel(
selectInput("plotType", "Plot Type",
c(Scatter = "scatter", Histogram = "hist")),
conditionalPanel(
condition = "input.plotType == 'hist'",
selectInput("breaks", "Breaks",
c("Sturges", "[Custom]" = "custom")),
conditionalPanel(
condition = "input.breaks == 'custom'",
sliderInput("breakCount", "Break Count", min = 1, max = 1000, value = 10)
)
)
)
)
server <- function(input, output) {}
shinyApp(ui, server)
Si condicionamos por una variable definida por el usuario:
- Nos referiremos a la variable como input.xxx, NO usaremos input$xxx.
ui <- fluidPage(
titlePanel("Shiny - tabsetPanel"),
mainPanel(
tabsetPanel(
tabPanel("Plot 1", plotOutput("plot1")),
tabPanel("Plot 2", plotOutput("plot2"))
)
)
)
server <- function(input, output) {
output$plot1 <- renderPlot(plot(cars))
output$plot2 <- renderPlot(plot(pressure))
}
shinyApp(ui, server)
ui <- fluidPage(
titlePanel("Shiny - navlistPanel"),
navlistPanel("PANELES",
tabPanel("Primer Panel",
plotOutput("plot1")),
tabPanel("Segundo Panel",
plotOutput("plot2"))
)
)
server <- function(input, output) {
output$plot1 <- renderPlot(plot(cars))
output$plot2 <- renderPlot(plot(pressure))
}
shinyApp(ui, server)
ui <- navbarPage("Shiny - navbarPage",
tabPanel("Primera Página",
plotOutput("plot1")),
tabPanel("Segunda Página",
plotOutput("plot2"))
)
server <- function(input, output) {
output$plot1 <- renderPlot(plot(cars))
output$plot2 <- renderPlot(plot(pressure))
}
shinyApp(ui, server)
Control widgets
¿Qué hacemos en el server.R?
Al referirnos a variables introducidas por el usuario mediante widgets definidos en el ui, emplearemos input$xxx, siendo xxx es el nombre indicado en el argumento InputID del widget correspondiente.
En el server es donde debemos realizaremos los cálculos y gráficos que queramos mostrar en el ui.
Shiny responde de forma inmediata a los cambios introducidos por el usuario pero, ¿siempre queremos esto?
En ocasiones nos interesará realizar un cálculo o un gráfico que dependa de más de una variable, ¿que sucedería si permitimos que Shiny nos de una respuesta instantáneamente?
Las funciones render*() crean una salida para mostrar por pantalla.
Los resultados de estas funciones siempre se guardan en output$.
output$hist <- renderPlot({
hist(rnorm(input$N))
})
Las expresiones reactive() generan un objeto para ser utilizado. Este objeto cambiará de valor cada vez que se modifique algún input$ de su interior.
El objeto generado se llama como una función.
data <- reactive({
rnorm(input$N)
})
output$hist <- renderPlot({
hist(data())
})
data <- reactive({
rnorm(input$N)
})
output$hist <- renderPlot({
hist(data(),
main = isolate(input$titulo))
})
ui <- fluidPage(
actionButton(inputId = "accion",
label = "Acción")
)
server <- function(input, output) {
observeEvent(input$accion, {
print(runif(1, 1, 100))
})
}
shinyApp(ui = ui, server = server)
ui <- fluidPage(
numericInput(inputId = "N", label = "Generar número aleatorio entre 0 y:", value = 100, min = 0, max = 300),
actionButton(inputId = "actualizar",
label = "Actualizar"),
textOutput("rnd")
)
server <- function(input, output) {
data <- eventReactive(input$actualizar, {
runif(1, 1, input$N)
})
output$rnd <- renderText({data()})
}
shinyApp(ui = ui, server = server)
-Estos valores reactivos pueden manejarse (usualmente mediante observeEvent())
ui <- fluidPage(
actionButton(inputId = "norm", label = "Normal"),
actionButton(inputId = "unif", label = "Uniforme"),
plotOutput("hist")
)
server <- function(input, output) {
rv <- reactiveValues(data = rnorm(100))
observeEvent(input$norm, { rv$data <- rnorm(100) })
observeEvent(input$unif, { rv$data <- runif(100) })
output$hist <- renderPlot({
hist(rv$data)
}) }
shinyApp(ui = ui, server = server)
RStudio Team. 2016. RStudio: Integrated Development Environment for R. Boston, MA: RStudio, Inc. http://www.rstudio.com/.
Wickham, H. 2015. Advanced R. Boca Raton, FL: CRC.